home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac100% 1998 November
/
MAC100-1998-11.ISO.7z
/
MAC100-1998-11.ISO
/
オンラインソフト定点観測
/
ユーティリティ
/
Mops 3.2.sea
/
Mops 3.2
/
Mops ƒ
/
Base
< prev
next >
Wrap
Text File
|
1998-06-03
|
15KB
|
592 lines
¥ Sept 92 mrh New words etc. moving closer to ANSI standard
¥ Jul 93 mrh Select{ removed - replaced by Select[ in caseMod
cr .( loading Base...)
false value ECHO? ¥ echo load to screen?
0 value ACTW
¥ Indentifies any active Mops window which
¥ should be idled. Will be set zero if we have, say,
¥ a dialog as the front window, but NOT if we're
¥ switched into the background.
0 value emb_obj_offs
¥ Saves the offs returned by <findM>, which we need
¥ for inline binding. We define it back here
¥ since it needs to be saved and restored over
¥ anything which types to the Mops window (which
¥ also causes <findM> to be called). In particular,
¥ EVALUATE and FRefill with echoing on, type to
¥ the Mops window.
¥ (* ... *) defines a multi-line comment, which can be very useful. Many
¥ Pascal compilers use these symbols - I thought it better not to use
¥ the C-style /* ... */ since */ already has a meaning.
¥ A useful improvement to the typical Pascal implementation is to keep a
¥ level count so that this kind of comment can be nested.
: (*
1 ¥ initial level count
BEGIN
Mword count 2dup
" (*" s=
IF 2drop 1 + ¥ increment level count
ELSE
" *)" s=
IF 1 - ¥ decrement level count
?dup 0EXIT ¥ and if zero, we're done
THEN
THEN
AGAIN ; immediate
¥ We redefine a few useful words to take advantage of our optimization.
: 1+ state IF 1 postpone literal postpone + ELSE 1 + THEN ; immediate
: 2+ state IF 2 postpone literal postpone + ELSE 2 + THEN ; immediate
: 3+ state IF 3 postpone literal postpone + ELSE 3 + THEN ; immediate
: 4+ state IF 4 postpone literal postpone + ELSE 4 + THEN ; immediate
: 1- state IF 1 postpone literal postpone - ELSE 1 - THEN ; immediate
: 2- state IF 2 postpone literal postpone - ELSE 2 - THEN ; immediate
: 3- state IF 3 postpone literal postpone - ELSE 3 - THEN ; immediate
: 4- state IF 4 postpone literal postpone - ELSE 4 - THEN ; immediate
: 2* state IF 1 postpone literal postpone << ELSE 1 << THEN ; immediate
: 2/ state IF 1 postpone literal postpone a>> ELSE 1 a>> THEN ; immediate
: 4* state IF 2 postpone literal postpone << ELSE 2 << THEN ; immediate
: 4/ state IF 2 postpone literal postpone a>> ELSE 2 a>> THEN ; immediate
¥ ANSI words
: CELL+ state IF postpone 4+ ELSE 4 + THEN ; immediate
: CELL- state IF postpone 4- ELSE 4 - THEN ; immediate
: CELLS state IF 2 postpone literal postpone << ELSE 2 << THEN ; immediate
: CHAR+ state IF postpone 1+ ELSE 1 + THEN ; immediate
: CHARS ; immediate
4 constant 1CELL ¥ Not ANSI, but useful
: RECURSE curr-def compile, ; immediate
: SAVE-INPUT
src-start src-len >in @ source-id 4 ;
: RESTORE-INPUT
dup 4 <> IF true EXIT THEN
drop
-> source-id >in ! -> src-len -> src-start false ;
¥ :NONAME is an ANSI word - the Standard defines the stack effect as:
¥ ( C: -- colon-sys ) ( S: -- xt )
¥ In Mops we implement the control-flow stack on the data stack, which
¥ the Standard allows, specifying that the control-flow stack items
¥ go above the data stack items. In this word, "colon-sys" is just a
¥ security marker (300), so we return this on top of the xt.
: :NONAME ( -- xt 300 )
(:) -2 w, ¥ set up compilation, comma in colon handler
DP ¥ xt = cfa
300 ¥ security marker - part of "control-sys" in the
¥ ANSI defn
;
¥ =========================
¥ These can be useful:
: UMAX 2dup u> IF drop ELSE nip THEN ;
: UMIN 2dup u< IF drop ELSE nip THEN ;
¥ .H and U.H print a number in hex, signed and unsigned respectively.
: .H base >r hex . r> -> base ;
: U.H base >r hex u. r> -> base ;
0 constant Z
: NULLOSSTR ['] z ;
: @WORD ¥ ( -- addr ) Retrieves next blank-delimited word from input stream.
bl word ;
: LIT ¥ ( n -- ) A state-smart version of LITERAL. Corresponds
¥ to LITERAL in Fig-Forth or original Neon, whereas our
¥ present LITERAL is Forth-83/ANSI.
state IF postpone literal THEN ; immediate
: 0, 0 , ; ¥ Compiles an empty cell
: @VAL intrp1 ; ¥ Compiles a number from input stream
: 'TYPE ¥ ( -- 4bytes ) OS type literal
pad 4 bl fill @word count 4 min
pad swap cmove pad @ postpone lit ; immediate
create BUF255 256 allot ¥ buffer for string operations
: >STR255 ¥ ( addr len addr -- addr )
¥ Converts a string to a Str255 at addr
dup >r place r> ;
: STR255 ¥ ( -- ^buf255 )
buf255 >str255 ;
: CHAR @word 1+ c@ ; ¥ ANSI - replaces ASCII
: [CHAR] @word 1+ c@ postpone literal ; immediate
: & ¥ ( -- c ) A shorter state-smart version.
@word 1+ c@ postpone lit ; immediate
: $ ¥ State-smart HEX literal word
base >r
hex Mword number postpone lit
r> -> base ; immediate
: LITW ¥ ( n -- )
$ 3D3C w, w, ;
: W intrp1 litw ; immediate
(* Trap compilation. When we're fully native on the PowerPC this will
become totally obsolete...
*)
: SAVA5 postpone doSavA5 ;
: RSTA5
$ CD4F w, ¥ exg a6,a7
$ 2A5F w, ; ¥ move.l (a7)+,a5
: (TRAP$) ¥ ( trap# -- ) Compiles a call to the given trap.
SavA5 w, RstA5 ;
: TRAP$ ¥ ( --<trap#> )
base >r
hex intrp1 (trap$)
r> -> base ; immediate
: (FDOS$) ¥ ( trap# -- )
$ 205E w, ¥ move.l (a6)+,a0 ; FCB pointer
SavA5 w, RstA5
$ 48C0 w, ¥ ext.l d0 ; Result
$ 2D00 w, ; ¥ move.l d0,-(a6)
: FDOS$ ¥ ( --<trap#> )
base >r
hex intrp1 (fdos$)
r> -> base ; immediate
¥ ============ PowerPC stuff ===========
¥ Once we're compiling PPC code, we have to keep the code and data areas
¥ distinct. DP points to the data area, so we now add CDP pointing to
¥ the code area.
0 value CDP
false value CROSSED? ¥ True once we've CROSSed into the PPC image.
: code, PPC? IF CDP ! 4 ++> CDP ELSE , THEN ;
: codeW, PPC? IF CDP w! 2 ++> CDP ELSE w, THEN ;
: codeC, PPC? IF CDP c! 1 ++> CDP ELSE c, THEN ;
: RESERVE ¥ ( len -- ) Allot and clear.
here over erase allot ;
: CODE_RESERVE
CDP over erase ++> CDP ;
' null vect PPC_HEADER
' 2drop vect ppc_sHdr
(* - now in Files.
: MARK_FILE ¥ ( addr len -- )
¥ This needs to know about the PPC, so we redefine it:
crossed?
IF >r pad r@ cmove
bl pad r@ + c! ¥ append a blank to the file name
pad r> 1+ ppc_sHdr ¥ lay down the header
file-mark codeW, ¥ with the file-mark as the "handler code"
0 code, 0 codeW, 0 code, ¥ no dir, no log, no date
ELSE
mark_file
THEN
;
*)
¥ ============ Resources ===========
0 value ResRefNum
: OpenResFile ¥ ( addr len -- ) Opens named resource file
>r >r word0 r> r> str255
trap$ a997 i->l ¥ call OpenResFile
dup -> ResRefNum
-1 = abort" resource file open failed" ;
: CloseResFile ¥ ( -- )
ResRefnum makeint trap$ a99a ;
: OPENMR ¥ Opens the Mops system resource file if necessary.
MRopen? ?EXIT ¥ Do nothing if already open
instld? ?EXIT ¥ or if this is an installed application
" mops.rsrc" OpenResFile
true -> MRopen? ;
: GETRES ¥ ( type resID -- handle )
0 down makeint trap$ a9a0 ; ¥ call GetResource
¥ 01Jan96 DBH redefine so addr is safe
: GETSTRING ¥ ( resID -- addr len ) Get the string with resource ID
openMR
0 swap makeint trap$ a9ba ¥ call getString
dup
IF @ count ( addr len )
pad swap ( addr pad len ) ¥ i.e. ( src dest len)
dup >r ¥ save len
cmove
pad r> ( addr len )
ELSE
0
THEN ;
: (TSTR) ¥ ( id# -- ) Prints string with given resID.
getString type ;
: X ['] (tstr) -> tstr ; ¥ We can't do -> outside a defn till Args loaded
x forget x
¥ Our normal error action is to call DIE with an error number. DIE calls
¥ SvErr to save the error info, then THROWs the error number. If no error
¥ handler has been installed, or only handlers which don't want that number
¥ and re-THROW it, the default action for THROW occurs. This calls DFLT-DIE.
: (DDIE) ¥ ( n -- )
setFwind
+echo 0 -> (err#) ¥ Clear error indicator from AppleEvents
dflt-err ; ¥ Display error info and abort
: x ['] (ddie) -> dflt-die ;
x forget x
: ?ERROR ¥ ( b -- ) Aborts and prints resource string if true.
¥ Usage: ?error 999
postpone if
intrp1 ( get err# ) postpone literal postpone die
postpone then ; immediate
: TYPE# ¥ Prints string for id# in stream
intrp1 postpone lit postpone (tStr) ; immediate
: (.RSTR) ¥ ( -- ) print "Msg# ..." then string with given resID
." Msg# " dup . ." : " (tStr) ;
: MSG# ¥ usage: " Msg# <number>"
intrp1 postpone lit postpone (.rStr) ; immediate
¥ ( -- #cells)
: RDEPTH rp0 rp@ - 4/ 2- ;
: ?RDEPTH rp@ sp0 20 + < ?error 116 ; ¥ err if rtn stk about to
¥ collide with data stk
: TO_BE_WRITTEN 79 die ;
¥ ========== Type checking ===========
¥ Sometimes we want to check that a non-object parameter to a word is of a
¥ certain type. We give it a unique type code and use TYPCHK.
: TYPCHK <> ?error 179 ;
¥ ========== Forward definitions ===========
: X setfWind +echo
cr ." From " r@ .id 2 spaces r@ .h cr 109 die ;
: FORWARD
colHdr
$ 487AFFFE , ¥ pea (start of this instrn)
['] x here 6 allot
(patch) ;
: :F 301
here ' (patch) (:) ;
: ;F (;) 301 ?defn ; immediate
forward BLD ¥ Used in CLASS. Needs to be down here so we never
¥ refer to it with a short branch. Kludge?
¥ Commonly needed error words. These are forward defined - the main
¥ application should provide a sensible definition, with a nice friendly
¥ alert box, to tell the user in a nice friendly way that things are up
¥ the creek.
forward NOMEM ¥ Call when (not if!) we run out of memory.
forward I/O_ERR ¥ ( err# -- ) Call when there's an I/O error.
: OK? ¥ ( rc -- ) A useful word to use after an I/O op.
?dup 0EXIT I/O_err ;
¥ ========= :PROC and ;PROC ============
: :PROC
colHdr here 6 allot
['] procEntry swap 6 aligned_move
(:) 303 ; immediate
: ;PROC immediate
postpone procExit (;)
303 ?defn ;
¥ ======== Various utility words needed later =========
¥ BECOME allows restarting at a given word, with all stacks
¥ empty. This is necessary in menu handlers and other areas
¥ that could create indefinite nesting situations.
' quit vect becomeXT
: BE sp0 sp! rp0 rp! becomeXT quit ;
: (BE) -> becomeXT be ;
: BECOME ¥ Usage: Become newWord - compiles code to Be at runtime
state
IF postpone ['] postpone (be)
ELSE ' -> becomeXT be
THEN ; immediate
: DATETIME
$ 20C @ ;
¥ ============ Tables, lists etc. ===============
(* With Mops 2.5 we're trying to be consistent with the way we delimit
various kinds of lists with { ... }. No, we're not trying to copy C,
but let's at least follow the "principle of minimum astonishment"!
Thus, with words like xts{, we'll allow a variant "xts {" where you
can put a space before the "{". This is very easy to implement, so
why not?
*)
forward { immediate
: GOBBLE{ ¥ gobbles a "{" which must follow as a separate word.
' ['] { <> ?error 113 ; ¥ "{" expected
: ) 123 die ; immediate ¥ ") read when no list is current"
: (}) 123 die ; immediate ¥ "unmatched }"
' (}) vect } immediate ¥ } will mean different things in different
¥ contexts.
: }OR)? ¥ ( cfa -- cfa b )
dup ['] } = over ['] ) = or ;
(*
: TABLE
<BUILDS 0 w, here 112
DOES> length ;
: END_TABLE
112 ?pairs
here over - ¥ table length (excluding length field)
swap 2- w! ; ¥ store in length field
*)
0 value CNT
: (LITS) ¥ stack compiled list of values starting at IP
w@(ip) ( count ) dup -> cnt
4* r> tuck + dup >r swap
do i @abs 4 +loop
cnt ;
: XTS{ ¥ State-smart word to compile or stack a list
¥ of xts. Pulls words from stream, until "}".
state IF postpone (lits) here 0 w, THEN
0
BEGIN ' }or)?
NWHILE state IF reloc, else swap THEN 1+
REPEAT
drop state IF swap w! THEN ; immediate
: CFAS{ postpone xts{ ; immediate ¥ Synonyms for compatibility
: CFAS( postpone xts{ ; immediate
: XTS gobble{ postpone xts{ ; immediate
(* SCON defines a string constant. Usage:
scon <name> "a string"
Runtime: ( -- addr len )
Change from Neon: the first nonblank char after the name of the SCON
becomes the delimiter. So " can be used as usual, but anything else can
be used instead, e.g.:
scon <name> /this string contains " as non-delimiter/
*)
: SCON
<BUILDS bl skip-src+
src-start >in @ + c@ ,dlm-str
DOES> count ;
¥ CASE should be used for non-contiguous or dynamically computed values.
¥ This is a modified Eaker/Duncan model.
¥ Our optimization strategy gives quite good code.
: CASE ?comp 302 ; immediate
: OF
postpone over postpone = postpone if
postpone drop ; immediate
: RANGEOF
postpone within? postpone if
postpone drop ; immediate
: ENDOF
postpone else ; immediate
: ENDCASE immediate
postpone drop
BEGIN dup 302 = NWHILE >resolve REPEAT drop ;
(* TYPE{ and ENUM{ (synonyms) define a Pascal/C-like enumerated type.
At this stage we don't give a name to the "type" as such, as we can't
do anything really sensible with it. However later we can optionally
load the ENUM-TYPE class which is rather more Pascal-like. But even
without that, the enumeration is very useful by itself.
*)
0 value TYPECNT
' null vect DO_ET ¥ Hook for handling the ENUM-TYPE
¥ class when it's loaded
: ENDLIST? ¥ ( chr -- b )
latest n>count 1 = down c@ = and
dup IF latest n>link (forget) THEN ;
: TYPE{
0 -> typeCnt ¥ 1st value
BEGIN typeCnt constant 1 ++> typeCnt
& } endlist?
UNTIL
do_ET ;
: ENUM{ type{ ; ¥ C fans might like this name better
: ENUM gobble{ type{ ;
¥ note we can't allow "type { ..." since "type" has another
¥ meaning already. But "enum { ..." is OK.
enum{ InMainDic InOtherMod InThisMod } ¥ Relocatable addr types
¥ ========== Error diagnostics ===========
¥ We use special values for nil handles and nil pointers. These are
¥ odd addresses in ROM, so that if we do a word or long access we will
¥ trap, and if we write a byte it at least won't go anywhere.
: .RTN ¥ ( addr -- )
cr ." From $" .h 4 spaces ;
: RANGE_ERR ¥ ( index range rtn-addr -- )
dup 1+ 0= ?error 128 ¥ Spurious range error
.rtn
dup -1 <
IF nip ?error 130 ¥ Not an indexed class
ELSE ." Range: " . ." Index: " .
true ?error 129
THEN ;
¥ If we do software mult and div (on a 68000 which only allows a 16-bit divisor or
¥ multiplicand) we also check for overflow and call ArithErr (vector) if ovfl occurs.
¥ The appropriate err# is on the stack already, so here we just set ArithErr to Die.
¥ This can be redirected as needed.
: X ['] range_err -> rngErr ['] die -> arithErr ;
x forget x
¥ =================== MARKER =====================
¥ On the PPC FORGET will be a bit limited, since we have a separate
¥ data area, which FORGET has no way of knowing about. So we'll
¥ discourage FORGET, and encourage use of the standard word MARKER.
: MARKER
DP
<builds
CDP displ, ( orig-DP ) displ,
does>
dup displace -> CDP 4+
displace -> DP 4+
DP (forget) ¥ fixes CONTEXT and LATEST
false -> echo? false -> PPC? false -> crossed?
;
load Args